package com.caishi.lkx.common.oplog;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.zzw.common.handler.ServletInvocableHandlerMethodCallback;
import com.zzw.common.handler.ServletInvocableHandlerPipeline;
import com.zzw.common.threadpool.SysThreadPool;
import com.caishi.lkx.common.context.UserContext;
import com.caishi.lkx.common.ienum.DeviceType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.HandlerMethod;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * @author by keray
 * date:2020/6/3 10:08 上午
 */
@Slf4j
@Configuration
public class AdminOpLogServletInvocableHandlerMethodHandler implements ServletInvocableHandlerPipeline {

    @Resource
    private UserContext userContext;

    @Resource
    private AdminOpLogMongoRepository logMongoRepository;

    @Override
    public int getOrder() {
        return 150;
    }

    @Override
    public Object work(HandlerMethod handlerMethod, Object[] args, NativeWebRequest request, Map<Object, Object> workContext, ServletInvocableHandlerMethodCallback callback) throws Exception {
        try {
            Object result = callback.get();
            var req = request.getNativeRequest(HttpServletRequest.class);
            if (req != null) {
                try {
                    SysThreadPool.execute(() -> addLog(result, args, handlerMethod, req.getMethod(), req.getRequestURI()));
                }catch (Exception ignore) {};
            }
            return result;
        } catch (Exception e) {
            throw e;
        }
    }

    private void addLog(Object result, Object[] args, HandlerMethod handlerMethod, String reqMethod, String url) {
        // 不是管理端不处理
        if (userContext.currentTokenData().getDevice() != DeviceType.admin || "GET".equals(reqMethod) || !userContext.loginStatus())
            return;
        //考研平台过滤用户记录api接口
        if(StrUtil.isBlank(url) ||"/user/log/admin".equals(url) || "/user/log/page".equals(url)){
            return;
        }
        var methodName = handlerMethod.getMethod().getDeclaringClass().getName() + "#" + handlerMethod.getMethod().getName();
        Map<String, Object> argsMap = new HashMap<>();
        for (var i = 0; i < args.length; i++) {
            argsMap.put("arg" + i, objectMap(args[i]));
        }
        var save = AdminOpLogModel.builder()
                .createdTime(System.currentTimeMillis())
                .userId(userContext.currentUserId())
                .duid(userContext.getDuid())
                .ip(userContext.currentIp())
                .infoId(userContext.currentTokenData().getInfoId())
                .tokenTime(userContext.currentTokenData().getTime())
                .role(String.join(",", userContext.currentTokenData().getUserRole()))
                .userType(userContext.currentTokenData().getUserTypeName())
                .methodName(methodName)
                .url(url)
                .reqMethod(reqMethod)
                .result(new HashMap<>() {{
                    put("result", objectMap(result));
                }})
                .args(argsMap)
                .build();
        logMongoRepository.insert(save);
    }

    private Object objectMap(Object o) {
        try {
            return JSON.parse(JSON.toJSONString(o));
        } catch (Exception e) {
            return String.format("参数解析失败 异常信息=%s", e.getMessage());
        }
    }
}
